using System;
using System.IO;
using System.Collections.Generic;

namespace KLib.Utilities
{
    /// <summary>
    /// Allows the program to output to a text file for error logging, event logging, and general debugging.
    /// </summary>
    public class Logger
    {
        #region Fields
        private static bool isTimeStampOn = true;
        private static bool enabled = false;

        private static StreamWriter log;
        private static string outputFileName;
        private static List<string> hookList;
        #endregion

        #region Properties

        #endregion

        #region Initialization

        /// <summary>
        /// Initializes the log with default values.
        /// </summary>
        public static void Initialize()
        {
            outputFileName = "run_time_log";
            log = File.AppendText(outputFileName + ".txt");
            enabled = true;
            AppendToFileNow("Logging enabled for this session.");
        }
        /// <summary>
        /// Initializes the log
        /// </summary>
        /// <param name="_outputFileName">The name of the file to be outputed, EXCLUDING the extension</param>
        public static void Initialize(string _outputFileName)
        {
            outputFileName = _outputFileName;
            log = File.AppendText(outputFileName + ".txt");
            enabled = true;
            AppendToFileNow("Logging enabled for this session.");
        }
        #endregion

        #region Methods

        /// <summary>
        /// Adds a message to the log file.
        /// </summary>
        public static void AppendToFile(string message)
        {
            if (enabled)
            {
                if (isTimeStampOn)
                    log.Write(DateTime.Now + ": ");

                log.WriteLine(message);

                if (hookList != null)
                    hookList.Add(message);
            }
        }

        /// <summary>
        /// Adds a message to the log file immidiatly. This should be used ONLY in debug situations
        /// as the preformance costs are much higher.
        /// </summary>
        public static void AppendToFileNow(string message)
        {
            if (enabled)
            {
                AppendToFile(message);
                log.Flush(); //Causes the log to be written, also causes preformance loss
            }
        }

        /// <summary>
        /// Enables the Time Time stamp on each message
        /// </summary>
        public static void EnableTimeStamp()
        {
            isTimeStampOn = true;
        }

        /// <summary>
        /// Disables the Time Time stamp on each message
        /// </summary>
        public static void DisableTimeStamp()
        {
            isTimeStampOn = false;
        }

        /// <summary>
        /// Closes the log, and writes remaining data to the file
        /// </summary>
        public static void CloseLog()
        {
            if (enabled)
            {
                //Log that the log is closeing
                AppendToFile("Logging ended for this session.");
                log.WriteLine();
                //Add the remaining messages to the log, and close the log
                log.Flush();
                log.Close();

                //We closed the log, so its no longer enabled :P
                enabled = false;
            }
        }

        /// <summary>
        /// Emptys the log file. Should only ever be called at the begining of a session.
        /// </summary>
        public static void ClearLog()
        {
            FileInfo file = new FileInfo(outputFileName + ".txt");

            log.Close();
            if (file.Exists)
                file.Delete();

            log = File.AppendText(outputFileName + ".txt");
        }

        /// <summary>
        /// Hooks a List of strings to recive messages.
        /// This means that whenever a message is appeneded to a file, will also be added to the hooked list.
        /// </summary>
        public static void Hook(List<string> _hookList)
        {
            hookList = _hookList;
        }
        #endregion
    }
}